<?php

/**
 * Dumps the contents of a public module asset.
 *
 * @author     Mon Zafra <monzee at gmail>
 * @copyright  (c)2009 Mon Zafra
 * @category   Mz
 * @package    modules
 * @subpackage modules
 * @license    http://mz-project.googlecode.com/svn/trunk/LICENSE    MIT License
 * @version    SVN: $Id: IndexController.php 48 2009-05-29 11:03:25Z monzee $
 * @todo Test for the possibility of getting a file outside of the public
 *       resource folder by using relative paths in the url
 */
class Modules_IndexController extends Zend_Controller_Action
{
    const DATE_FORMAT = 'D, d M Y H:i:s \G\M\T';

    const MAX_AGE = 2592000; // 30 days in seconds

    protected $_types = array(
        'css' => 'text/css',
        'bmp' => 'image/bmp',
        'gif' => 'image/gif',
        'jpg' => 'image/jpeg',
        'jpeg'=> 'image/jpeg',
        'png' => 'image/png',
        'js'  => 'text/javascript',
        'html'=> 'text/html',
        'htm' => 'text/html',
        'txt' => 'text/plain',
    );

    /**
     * All calls end up here if the route is set properly.
     *
     * @return void
     */
    public function indexAction()
    {
        $req = $this->_request;
        $res = $this->_response;
        $front = $this->getInvokeArg('bootstrap')->getResource('frontcontroller');

        $targetModule = $req->getParam('target');
        $asset = $req->getParam('asset');
        $assetDir = $this->getInvokeArg('assetDirectory');

        $file = realpath(
            rtrim($front->getControllerDirectory($targetModule), '\\/')
            . '/../' . (null === $assetDir ? 'public' : $assetDir) . '/' . $asset
        );

        $this->_helper->viewRenderer->setNoRender(true);
        if (Zend_Controller_Action_HelperBroker::hasHelper('Layout')) {
            $this->_helper->layout->disableLayout();
        }

        if (file_exists($file)) {
            $ext = pathinfo($file, PATHINFO_EXTENSION);
            $modTime = filemtime($file);
            $age = self::MAX_AGE;
            // TODO: consider X-Sendfile header
            // http://www.noginn.com/2009/03/08/sending-files-with-the-zend-framework/
            $res->setHeader('Content-Type', $this->_getType($ext))
                ->setHeader('Cache-Control', 'public, max-age=' . $age, true)
                ->setHeader('Last-Modified', gmdate(self::DATE_FORMAT, $modTime), true)
                ->setHeader('Expires', gmdate(self::DATE_FORMAT, time() + $age), true)
                ->setHeader('Pragma', null, true);

            $lastMod = $req->getHeader('If-Modified-Since');
            if (!empty($lastMod) && $modTime <= strtotime($lastMod)) {
                $res->setHttpResponseCode(304); // Not modified
                return;
            }

            readfile($file); // read and output directly
        } else {
            $res->setHttpResponseCode(404); // Not found
        }
    }

    /**
     * Returns mime type according to extension.
     *
     * @param string $ext     File extension
     * @param string $default The type to return if the extension is unknown
     * @return string
     */
    protected function _getType($ext, $default = 'text/plain')
    {
        return isset($this->_types[$ext]) ? $this->_types[$ext] : $default;
    }

}
